// 包含计算温湿度的模块
#include "dht11.h"

// 定义用于计算温湿度的变量
dht11 DHT11;

// 温湿度引脚定义
#define DHT11PIN 2
// 定义人体红外引脚
#define PeoplePIN 3
// 定义可燃气体引脚
#define FirePIN 4
// 定义排气继电器引脚
#define AirPIN 5
// 定义蜂鸣器引脚
#define BeepPIN 6

// 定义温湿度变量
float temp = 0;
float humidity = 0;
// 定义限位器变量
int people = 0;
// 定义可燃气体变量
int fire = 0;
// 定义排气继电器变量
int air = 0;
// 定义照明LED变量
int beep = 0;

// 定义字符串接收缓冲区
String data = "";
// 定义发送数据的时间间隔
int data_send_interraval = 2000;
int data_send_counter = 0;

/*获取当前温度湿度*/
void getTempAndHumidity() {
  // 读取温度并判断是否读取成功
  int chk = DHT11.read(DHT11PIN);
  if (DHTLIB_OK == chk) {
    temp = (float)DHT11.temperature;
    humidity = (float)DHT11.humidity;
  } else {
    temp = 0;
    humidity = 0;
  }
}

/*获取人体红外*/
void getpeople() {
  people = !digitalRead(PeoplePIN);

  /*设置蜂鸣器*/
  if (beep && people) { // 如果开启蜂鸣器
    digitalWrite(BeepPIN, HIGH);
  } else {
    digitalWrite(BeepPIN, LOW);
  }
}

/*获取可燃气体*/
void getFire() {
  fire = !digitalRead(FirePIN);
  if (air && fire) { // 如果开启自动排气
    digitalWrite(AirPIN, HIGH);
  } else {
    digitalWrite(AirPIN, LOW);
  }
}

/*采集数据并发送数据*/
void sampleAndSendData() {
  getTempAndHumidity();
  getpeople();
  getFire();
  // 采用json数据包的方式将数据发送出去
  Serial.print("{\"temp\":");
  Serial.print(temp);
  Serial.print(",\"home\":");
  Serial.print(people);
  Serial.print(",\"fire\":");
  Serial.print(fire);
  Serial.print(",\"air\":");
  Serial.print(air);
  Serial.print(",\"beep\":");
  Serial.print(beep);
  Serial.print(",\"humidity\":");
  Serial.print(humidity);
  Serial.println("}");
}

/*解析上位机发送的json数据并进行相应的设置*/
void resolveJsonAndSetHardWare(String json) {
  // 完整的json数据包格式
  // {"B":0,"A":1}
  
  // 处理蜂鸣器
  if (json[5] == '0') {
    beep = 0;
  } else {
    beep = 1;
  }

  // 处理排气
  if (json[11] == '0') {
    air = 0;
  } else {
    air = 1;
  }
}

void setup() {
  // [0] 初始化串口
  Serial.begin(115200);

  // [1] 初始化其它相关的引脚
  pinMode(PeoplePIN, INPUT);
  pinMode(FirePIN, INPUT);
  pinMode(AirPIN, OUTPUT);
  pinMode(BeepPIN, OUTPUT);
}

void loop() {
  // [0] 获取控制状态信息并进行相应的数据解析
  while (Serial.available() > 0) {
    data += char(Serial.read());
  }
  // [1] json 数据接收完成
  if (data[0] == '{' && data[12] == '}') {
    resolveJsonAndSetHardWare(data);
    data = "";
  }

  // [2] 判断是否到了发送数据的时间
  if (data_send_interraval == data_send_counter) {
    // (0) 采集一次数据并发送数据
    sampleAndSendData();
    data_send_counter = 0;
  } else {
    data_send_counter += 10;
  }
  // 适当延时避免数据缓冲区溢出
  delay(10);
}
